package com.pan.util;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.google.gson.Gson;
import com.pan.entity.Order;
import com.pan.entity.OrderInvoice;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.SerializationUtils;

import java.io.*;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.math.BigDecimal;

@Slf4j
public class DeepCloneUtil {

    /**
     * 生成一个order实例
     * 向下转型只能强转（Order）Object
     * @return
     * @throws ClassNotFoundException
     * @throws IllegalAccessException
     * @throws InstantiationException
     */
    public static Order getOneOrderObject() throws ClassNotFoundException, IllegalAccessException, InstantiationException {
        Order order = (Order)Class.forName(Order.class.getName()).newInstance();

        Field[] fields = order.getClass().getDeclaredFields();
        for (Field field : fields) {
            Class<?> type = field.getType();
            field.setAccessible(true);
            //判断是否为final
            if(Modifier.isFinal(field.getModifiers())){
                continue;
            };
            if(type.equals(String.class)){
                field.set(order,"hello");
                log.info("feildName:{}",field.getName());
            }else if(type.equals(BigDecimal.class)){
                field.set(order,BigDecimal.ONE);
                log.info("feildName:{}",field.getName());
            }else if(type.equals(OrderInvoice.class)){
                OrderInvoice invoice = (OrderInvoice) Class.forName(type.getName()).newInstance();
                Field[] declaredFields = invoice.getClass().getDeclaredFields();
                for (Field declaredField : declaredFields) {
                    declaredField.setAccessible(true);
                    Class<?> type1 = declaredField.getType();
                    if(type1.equals(String.class)){
                        declaredField.set(invoice,"invoice");
                    }

                }
                invoice.setOrder(order);
                order.setOrderInvoice(invoice);
            }
        }
        return order;
    }

    /**
     * 若对象相互嵌套，会堆栈溢出
     * @param order
     */
    public static  void gsonOrder(Order order){
        Gson gson = new Gson();
        Order orderClone =  gson.fromJson(gson.toJson(order),Order.class);
        log.info("order{}",orderClone);
    }


    public static  void cloneOrder(Order order) throws CloneNotSupportedException {
        Order cloneOrder = order.clone();
        log.info("cloneOrder :",cloneOrder);
    }


    public static <T> T deepCopyByJson(T obj,Class<T> t) {
        String json = JSON.toJSONString(obj);
        return JSON.parseObject(json, t);
    }

    public static <T> T deepCloneObject(T obj) {
        try {
            ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
            ObjectOutputStream out = new ObjectOutputStream(byteOut);
            out.writeObject(obj);

            ByteArrayInputStream byteIn = new ByteArrayInputStream(byteOut.toByteArray());
            ObjectInputStream in =new ObjectInputStream(byteIn);

            return (T)in.readObject();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        return null;
    }


    public static void main(String[] args) throws IllegalAccessException, InstantiationException, ClassNotFoundException, CloneNotSupportedException {
       Order order =  getOneOrderObject();
       log.info(JSONObject.toJSONString(order));
       cloneOrder(order);
       Order order1 = deepCopyByJson(order,Order.class);
        //gsonOrder(order);
        Order clone = (Order) SerializationUtils.clone(order);
        Order clone2 =deepCloneObject(order);
    }



}
